package com.bcbim.api_model.component.controller;

import com.bcbim.common.response.vo.ReturnMsg;
import com.bcbim.common.sys.ParamException;
import com.bcbim.common.util.ParamCheck;
import com.bcbim.model_server_interface.component.bo.ComponentTreeBO;
import com.bcbim.model_server_interface.component.dto.CategoryComponentDTO;
import com.bcbim.model_server_interface.component.dto.ComponentMaterialDTO;
import com.bcbim.model_server_interface.component.service.ComponentService;
import com.bcbim.model_server_interface.component.vo.*;
import com.bcbim.model_server_interface.file.service.FileService;
import com.bcbim.model_server_interface.floor.service.FloorService;
import com.bcbim.model_server_interface.floor.vo.FloorInfoVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 构件查询接口
 * @Author: ye
 * @Date: 2022/4/12
 * @Version: V1.0
 **/
@RestController
@RequestMapping("component")
public class ComponentController {

    @Reference(protocol = "dubbo", group = "component", version = "1.0.0")
    private ComponentService componentServiceImpl;
    @Reference(protocol = "dubbo", group = "floor", version = "1.0.0")
    private FloorService floorServiceImpl;
    @Reference(protocol = "dubbo", group = "file", version = "1.0.0")
    private FileService fileServiceImpl;

    /**
     * @Description: 查询组件mash的索引
     * @Param: GetComponentMashDTO
     * @Return: ReturnMsg
     * @Author: ye
     * @Date: 2022/3/29
     */
    @PostMapping("getComponent")
    public ReturnMsg getComponent(ComponentMaterialDTO query) {
        try {
            ParamCheck.idCheck(query.getMaterialId());
            ParamCheck.notNull(query.getFaceIndex());
        } catch (Exception e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        ComponentMaterialVO component = new ComponentMaterialVO(componentServiceImpl.getComponentId(query));
        if (StringUtils.isEmpty(component.getComponentId())) {
            return ReturnMsg.consSuccess(null);
        }
        List<MaterialIndexVO> list = componentServiceImpl.getComponentMashById(component.getComponentId());
        component.setList(list);
        return ReturnMsg.consSuccess(component);
    }

    /**
     * @Description: 查询组件树
     * @Param: fileId
     * @Return: ReturnMsg
     * @Author: ye
     * @Date: 2022/3/29
     */
    @PostMapping("getComponentTree")
    public ReturnMsg getComponentTree(String[] arrFileId) {
        if (checkArrId(arrFileId)) return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);

        List<ComponentTreeVO> list = new ArrayList<>();

        for (int i = 0; i < arrFileId.length; i++) {
            ComponentTreeVO fileTree = generateComponentTree(arrFileId[i], i);
            if (fileTree != null) {
                list.add(fileTree);
            }
        }

        return ReturnMsg.consSuccess(list);
    }

    public static boolean checkArrId(String[] arrFileId) {
        if (arrFileId == null || arrFileId.length == 0) {
            return true;
        }
        for (String id : arrFileId) {
            try {
                ParamCheck.idCheck(id);
            } catch (ParamException e) {
                return true;
            }
        }
        return false;
    }

    private ComponentTreeVO generateComponentTree(String id, int index) {

        ComponentTreeBO fileRoot = fileServiceImpl.getFileRoot(id);
        if (fileRoot == null) {
            return null;
        }
        List<ComponentTreeBO> treeList = componentServiceImpl.getComponentTree(id);
        List<ComponentTreeBO> componentList = componentServiceImpl.getComponentTreeComponent(id);
        Map<String, List<ComponentTreeVO>> componentMap = new HashMap<>();

        List<ComponentTreeVO> result = new ArrayList<>();

        for (ComponentTreeBO componentTreeBO : componentList) {
            if (componentMap.containsKey(componentTreeBO.getParentId())) {
                componentMap.get(componentTreeBO.getParentId()).add(new ComponentTreeVO(componentTreeBO));
            } else {
                List<ComponentTreeVO> list = new ArrayList<>();
                list.add(new ComponentTreeVO(componentTreeBO));
                componentMap.put(componentTreeBO.getParentId(), list);
            }
        }

        int code = 0;
        for (ComponentTreeBO componentTreeBO : treeList) {
            if (StringUtils.isEmpty(componentTreeBO.getParentId())) {
                ComponentTreeVO componentTreeVO = new ComponentTreeVO(componentTreeBO);
                componentTreeVO.setChildren(getChildren(componentTreeVO.getId(), treeList, componentMap, 0, index + "-" + code));
                result.add(componentTreeVO);
                code++;
            }
        }
        ComponentTreeVO root = new ComponentTreeVO(fileRoot);
        root.setChildren(result);
        root.setCode(String.valueOf(index));
        return root;
    }

    /**
     * @Description: 查询子节点
     * @Param: parentId 上级id
     * @Param: List<ComponentTreeBO> 组件数
     * @Param: Map<String, List < ComponentTreeVO>> 组件的map映射
     * @Param: deep 循环深度
     * @Param: parentCode 每一级索引
     * @Return: List<ComponentTreeVO>
     * @Author: ye
     * @Date: 2022/3/30
     */
    private List<ComponentTreeVO> getChildren(String parentId, List<ComponentTreeBO> treeList, Map<String, List<ComponentTreeVO>> componentMap, int deep, String parentCode) {
        if (deep == 3) {
            for (ComponentTreeVO treeVO : componentMap.get(parentId)) {
                treeVO.setCode(parentCode);
            }
            return componentMap.get(parentId);
        }
        int code = 0;
        List<ComponentTreeVO> children = new ArrayList<>();
        for (ComponentTreeBO componentTreeBO : treeList) {
            if (parentId.equals(componentTreeBO.getParentId())) {
                ComponentTreeVO treeVO = new ComponentTreeVO(componentTreeBO);
                int _deep = deep;
                treeVO.setCode(parentCode);
                treeVO.setChildren(getChildren(treeVO.getId(), treeList, componentMap, ++_deep, parentCode + "-" + code));
                code++;
                children.add(treeVO);
            }
        }
        return children;
    }

    /**
     * @Description: 根据id查询组件信息
     * @Param: GetComponentMashDTO
     * @Return: ReturnMsg
     * @Author: ye
     * @Date: 2022/3/29
     */
    @PostMapping("getComponentById")
    public ReturnMsg getComponentById(String componentId) {
        try {
            ParamCheck.idCheck(componentId);
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        ComponentMaterialVO component = new ComponentMaterialVO(componentServiceImpl.getComponentInfo(componentId));
        if (StringUtils.isEmpty(component.getComponentId())) {
            return ReturnMsg.consSuccess(null);
        }
        List<MaterialIndexVO> list = componentServiceImpl.getComponentMashById(component.getComponentId());
        component.setList(list);
        return ReturnMsg.consSuccess(component);
    }

    /**
     * @Description: 根据id数据查询构件信息
     * @Param: String[]
     * @Return: ReturnMsg
     * @Author: ye
     * @Date: 2022/6/2
     */
    @PostMapping("getArrComponentById")
    public ReturnMsg getArrComponentById(String[] componentIds) {
        if (componentIds == null) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        try {
            for (String componentId : componentIds) {
                ParamCheck.idCheck(componentId);
            }
        } catch (Exception e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        ArrComponentMeshVO result = new ArrComponentMeshVO();
        result.setComponents(componentServiceImpl.getArrComponentsById(componentIds));
        result.setMaterials(componentServiceImpl.getArrComponentMashById(componentIds));
        return ReturnMsg.consSuccess(result);
    }

    /**
     * @Description: 查询楼层的相关构件
     * @Param: floorId
     * @Return: ReturnMsg
     * @Author: ye
     * @Date: 2022/4/18
     */
    @PostMapping("getFloorModel")
    public ReturnMsg getFloorModel(String floorId) {
        try {
            ParamCheck.idCheck(floorId);
        } catch (ParamException e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }

        List<MaterialIndexVO> list = floorServiceImpl.getFloorModel(floorId);
        FloorInfoVO infoVO = new FloorInfoVO();
        infoVO.setFileId(floorServiceImpl.getFileId(floorId));
        infoVO.setList(list);
        FloorComponentVO result = new FloorComponentVO();
        result.setMaterials(list);
        result.setComponentIds(componentServiceImpl.getFloorComponentId(floorId));
        result.setFileId(floorServiceImpl.getFileId(floorId));
        return ReturnMsg.consSuccess(result);
    }

    /**
     * @Description: 根据类别获取所有构件
     * @Param: CategoryComponentDTO
     * @Return: ReturnMsg
     * @Author: ye
     * @Date: 2022/4/29
     */
    @PostMapping("getComponentByCategory")
    public ReturnMsg getComponentByCategory(CategoryComponentDTO query) {
        try {
            ParamCheck.idCheck(query.getFileId());
        } catch (Exception e) {
            return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        }
        List<ComponentInfoVO> list = componentServiceImpl.getComponentByCategory(query);
        return ReturnMsg.consSuccess(list);
    }

    /**
     * @Description: 查询构件中点
     * @Param: String[]
     * @Return: ReturnMsg
     * @Author: ye
     * @Date: 2022/6/6
     */
    @PostMapping("getComponentCenter")
    public ReturnMsg getComponentCenter(String[] arrFileId) {
        if (checkArrId(arrFileId)) return ReturnMsg.consFail(ParamException.PARAMETER_ERROR);
        List<ComponentCenterVO> list = componentServiceImpl.getComponentCenter(arrFileId);
        return ReturnMsg.consSuccess(list);
    }

}
